home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / PlayerPRO 4.4.1 Dev.Kit / Import⁄Export / S3M2Mad.c < prev   
Encoding:
Text File  |  1995-04-07  |  15.1 KB  |  625 lines  |  [TEXT/MPCC]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.4x -- S3M to MADx
  4. //
  5. //    Version 1.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:    100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "S3M.h"
  21. #include "MAD.h"
  22. #include "RDriver.h"
  23. #include "PPInOut.h"
  24.  
  25. #if defined(powerc) || defined(__powerc)
  26. enum {
  27.         PlayerPROPlug = kCStackBased
  28.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  29.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  30.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  31.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  32.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  33.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( short**)))
  34. };
  35.  
  36. ProcInfoType __procinfo = PlayerPROPlug;
  37. #else
  38. #include <A4Stuff.h>
  39. #endif
  40.  
  41. short FoundNoteS3M( short Period)
  42. {
  43. short    NCount = 1;
  44.     
  45.     while( NCount < 85)
  46.      {
  47.             if( Period >= pitchTable[ NCount][ 0])
  48.             {
  49.                 return( NCount);
  50.             }
  51.             NCount++;
  52.     }
  53.     return 0;
  54. }
  55.  
  56. unsigned long Tdecode32( void *msg_buf)
  57. {
  58.   unsigned char *buf = msg_buf;
  59.   
  60.   return( (unsigned long) buf[3] << 24) | ( (unsigned long) buf[2] << 16) | ( (unsigned long) buf[ 1] << 8) | ( (unsigned long) buf[0]);
  61. }
  62.  
  63. short Tdecode16( void *msg_buf)
  64. {
  65.   unsigned char *buf = msg_buf;
  66.   
  67.   return ( (short) buf[1] << 8) | ( (short) buf[0]);
  68. }
  69.  
  70. struct Command* GetCommand( register short PosX, register short    TrackIdX, register    struct MusicPattern*    tempMusicPat)
  71. {
  72.     if( PosX < 0) PosX = 0;
  73.     else if( PosX >= tempMusicPat->header.PatternSize) PosX = tempMusicPat->header.PatternSize -1;
  74.         
  75.     return( & (tempMusicPat->Commands[ (tempMusicPat->header.PatternSize * TrackIdX) + PosX]));
  76. }
  77.  
  78. void ConvertS3MEffect( Byte B0, Byte B1, Byte *Cmd, Byte *Arg)
  79. {
  80.     Str255    tStr;
  81.     
  82.     switch( B0 + 0x40)
  83.     {
  84.     /*    default:
  85.             NumToString( B0 + 0x40, tStr);
  86.             DebugStr( tStr);
  87.         break;*/
  88.     
  89.         case 'A':
  90.             *Cmd = speedE;        *Arg = B1;
  91.         //    if( *Arg >= 0x10 || *Arg < 0x1F) *Arg -= 0x10;
  92.         break;
  93.         
  94.         case 'B':
  95.             *Cmd = fastskipE;        *Arg = B1;
  96.         break;
  97.  
  98.         case 'C':
  99.             *Cmd = skipE;            *Arg = B1;
  100.         break;
  101.  
  102.         case 'D':
  103.             *Cmd = slidevolE;        *Arg = B1;
  104.         break;
  105.         
  106.         case 'E':
  107.             *Cmd = upslideE;        *Arg = B1;
  108.         break;
  109.  
  110.         case 'F':
  111.             *Cmd = downslideE;        *Arg = B1;
  112.         break;
  113.  
  114.         case 'G':
  115.             *Cmd = portamentoE;    *Arg = B1;
  116.         break;
  117.  
  118.         case 'H':
  119.             *Cmd = vibratoE;        *Arg = B1;
  120.         break;
  121.  
  122.         case 'J':
  123.             *Cmd = arpeggioE;        *Arg = B1;
  124.         break;
  125.  
  126.         case 'K':
  127.             *Cmd = vibratoslideE;    *Arg = B1;
  128.         break;
  129.         
  130.         case 'O':
  131.             *Cmd = portaslideE;        *Arg = B1;
  132.         break;
  133.  
  134.         case 'P':
  135.             *Cmd = offsetE;        *Arg = B1;
  136.         break;
  137.  
  138.         case 'S':        // Not implemented
  139.             *Cmd = 0;            *Arg = 0;
  140.         break;
  141.  
  142.         case 'T':        // Not implemented
  143.             *Cmd = 0;            *Arg = 0;
  144.         break;
  145.  
  146.         case 'V':        // Not implemented
  147.             *Cmd = 0;            *Arg = 0;
  148.         break;
  149.  
  150.         case 'X':        // Not implemented
  151.             *Cmd = 0;            *Arg = 0;
  152.         break;
  153.  
  154.         case 'Z':        // Not implemented
  155.             *Cmd = 0;            *Arg = 0;
  156.         break;
  157.     }
  158. }
  159.  
  160. OSErr ConvertS3M2Mad( Ptr    theS3M, long MODSize, MADPartition *theMAD)
  161. {
  162.     long                 i, PatMax, x, z, channel, Row;
  163.     long                 sndSize, OffSetToSample, OldTicks, temp, starting;
  164.     Ptr                MaxPtr;
  165.     OSErr            theErr;
  166.     Ptr                theInstrument[ 64], destPtr;
  167.     Byte                tempChar, *theS3MCopy;
  168.     short            Note, Octave, maxTrack;
  169. //    short            S3Mperiod[ 12] = {1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907};
  170.     long                note_st3period;
  171.     long                note_amigaperiod;
  172.     Byte                *ChannelSettings;
  173.     
  174.     /**** Variables pour le MAD ****/
  175.     struct Command        *aCmd;
  176.  
  177.     /**** Variables pour le S3M ****/
  178.     
  179.     s3mform            s3minfo;
  180.     /********************************/
  181.  
  182.     for( i = 0 ; i < 64; i ++)
  183.     {
  184.         theInstrument[ i] = 0L;
  185.     }
  186.  
  187.     /**** Header principal *****/
  188.     theS3MCopy = (Byte*) theS3M;
  189.     BlockMove( theS3MCopy, &s3minfo, 96);
  190.     theS3MCopy += 96;
  191.     
  192.     s3minfo.ordernum    = Tdecode16(  &s3minfo.ordernum);
  193.     s3minfo.insnum        = Tdecode16(  &s3minfo.insnum);
  194.     s3minfo.patnum        = Tdecode16(  &s3minfo.patnum);
  195.     s3minfo.flags        = Tdecode16(  &s3minfo.flags);
  196.     s3minfo.cwtv        = Tdecode16(  &s3minfo.cwtv);
  197.     s3minfo.ffv        = Tdecode16(  &s3minfo.ffv);
  198.  
  199.     /**** Order Num *****/
  200.     s3minfo.orders = (unsigned char *) NewPtr( s3minfo.ordernum);
  201.     BlockMove( theS3MCopy, s3minfo.orders, s3minfo.ordernum);
  202.     theS3MCopy += s3minfo.ordernum;
  203.     
  204.     /**** Ins Num *****/
  205.     s3minfo.parapins = (unsigned short *) NewPtr( s3minfo.insnum * 2L);
  206.     BlockMove( theS3MCopy, s3minfo.parapins, s3minfo.insnum * 2L);
  207.     theS3MCopy += s3minfo.insnum * 2L;
  208.     for( i = 0; i < s3minfo.insnum; i++)
  209.     {
  210.         s3minfo.parapins[ i] = Tdecode16(  &s3minfo.parapins[ i]);
  211.     }
  212.     
  213.     
  214.     /**** Pat Num *****/
  215.     s3minfo.parappat = (unsigned short *) NewPtr( s3minfo.patnum * 2L);
  216.     BlockMove( theS3MCopy, s3minfo.parappat, s3minfo.patnum * 2L);
  217.     theS3MCopy += s3minfo.patnum * 2L;
  218.     for( i = 0; i < s3minfo.patnum; i++)
  219.     {
  220.         s3minfo.parappat[ i] = Tdecode16(  &s3minfo.parappat[ i]);
  221.     }
  222.  
  223.     /**** Ins Data ****/
  224.     s3minfo.insdata = (s3minsform *) NewPtr( sizeof(s3minsform) * s3minfo.insnum);
  225.     for (i = 0; i < s3minfo.insnum; i++)
  226.     {
  227.         theS3MCopy = (Byte*) theS3M;
  228.         theS3MCopy += s3minfo.parapins[i]*16L;
  229.         
  230.         BlockMove( theS3MCopy, &s3minfo.insdata[i], sizeof(s3minsform));
  231.         
  232.         s3minfo.insdata[i].insmemseg = Tdecode16( &s3minfo.insdata[i].insmemseg);
  233.         s3minfo.insdata[i].inslength = Tdecode32( &s3minfo.insdata[i].inslength);
  234.         s3minfo.insdata[i].insloopbeg = Tdecode32( &s3minfo.insdata[i].insloopbeg);
  235.         s3minfo.insdata[i].insloopend = Tdecode32( &s3minfo.insdata[i].insloopend);
  236.         s3minfo.insdata[i].insloc2spd = Tdecode16(  &s3minfo.insdata[i].insloc2spd);
  237.         s3minfo.insdata[i].inshic2spd = Tdecode16(  &s3minfo.insdata[i].inshic2spd);
  238.         s3minfo.insdata[i].insgvspos = Tdecode16(  &s3minfo.insdata[i].insgvspos);
  239.         s3minfo.insdata[i].insint512 = Tdecode16(  &s3minfo.insdata[i].insint512);
  240.         s3minfo.insdata[i].insintlastused = Tdecode32( &s3minfo.insdata[i].insintlastused);
  241.     
  242.         if (s3minfo.insdata[i].instype == 1)
  243.             {
  244.                 theS3MCopy = (Byte*) theS3M;
  245.                 theS3MCopy += s3minfo.insdata[i].insmemseg*16L;
  246.                 
  247.                 theInstrument[ i] = (Ptr) theS3MCopy;
  248.             }
  249.             else theInstrument[ i] = 0L;
  250.     }
  251.  
  252.     /******** Le S3M a été lu et analysé ***********/
  253.     /******** Copie des informations dans le MAD ***/
  254.     
  255.     theMAD->header = (MADSpec*) NewPtrClear( sizeof( MADSpec));    
  256.     theMAD->header->MADIdentification = 'MADG';
  257.     for(i=0; i<32; i++) theMAD->header->NameSignature[i] = 0;
  258.     for(i=0; i<28; i++) theMAD->header->NameSignature[i] = s3minfo.name[i];
  259.  
  260.     theMAD->header->PatMax        = s3minfo.patnum;
  261.     theMAD->header->numPointers    = s3minfo.ordernum;
  262.     
  263.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = 0;
  264.     for(i=0; i<s3minfo.ordernum; i++)
  265.     {
  266.         theMAD->header->oPointers[ i] = s3minfo.orders[i];
  267.         
  268.         if( theMAD->header->oPointers[ i] < 0 || theMAD->header->oPointers[ i] > s3minfo.patnum) theMAD->header->oPointers[ i] = 0;
  269.     }
  270.  
  271.     /********************/
  272.     /***** INSTRUMENTS *****/
  273.     /********************/
  274.  
  275.     for(i=0; i<s3minfo.insnum; i++)
  276.     {
  277.         for( x = 0; x < 28; x++) theMAD->header->fid[i].Filename[x] = s3minfo.insdata[i].insname[x];
  278.         theMAD->header->fid[i].insSize = s3minfo.insdata[i].inslength;
  279.         theMAD->header->fid[i].fineTune = 0;
  280.         theMAD->header->fid[i].volume = s3minfo.insdata[i].insvol;
  281.         theMAD->header->fid[i].freq = 1;
  282.         theMAD->header->fid[i].amplitude = 8;
  283.         theMAD->header->fid[i].loopStart = s3minfo.insdata[i].insloopbeg;
  284.         theMAD->header->fid[i].loopLenght = s3minfo.insdata[i].insloopend - s3minfo.insdata[i].insloopbeg + 2;
  285.         
  286.         if( theMAD->header->fid[i].insSize > 0)
  287.         {
  288.             theMAD->instrument[i] = NewPtr( theMAD->header->fid[i].insSize);
  289.             BlockMove( theInstrument[i], theMAD->instrument[i], theMAD->header->fid[i].insSize);
  290.             
  291.             destPtr = theMAD->instrument[i];
  292.             for( temp = 0; temp < theMAD->header->fid[i].insSize; temp++)
  293.             {
  294.                 *(destPtr + temp) -= 0x80;
  295.             }
  296.         }
  297.         else theMAD->instrument[i] = 0L;
  298.     }
  299.  
  300.     for(i  = s3minfo.insnum ; i < MAXINSTRU; i++)
  301.     {
  302.         theInstrument[i] = 0L;
  303.         theMAD->header->fid[i].freq = 1;
  304.         theMAD->header->fid[i].amplitude = 8;
  305.         theMAD->header->fid[i].volume = 64;
  306.     }
  307.     /********************/
  308.     
  309.     /*********************/
  310.     /*           Check MaxTrack         */
  311.     /*********************/
  312.     maxTrack = 0;
  313.     for( i = 0; i < theMAD->header->PatMax ; i++)
  314.     {
  315.         Row = 0;
  316.         
  317.         theS3MCopy = (Byte*) theS3M;
  318.         theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  319.         theS3MCopy++;
  320.         
  321.         while( Row < 64)
  322.         {
  323.             tempChar = *theS3MCopy;
  324.             theS3MCopy++;
  325.  
  326.             if( tempChar == 0) Row++;
  327.             else
  328.             {    // Channel
  329.                 channel = tempChar;
  330.                 channel &= 31;
  331.                 
  332.                 if( channel > maxTrack) maxTrack = channel;
  333.                 
  334.                 if( (tempChar & 32) != 0) theS3MCopy += 2L;
  335.                 if( (tempChar & 64) != 0) theS3MCopy += 1L;
  336.                 if( (tempChar & 128) != 0) theS3MCopy += 2L;
  337.             }
  338.         }
  339.     }
  340.     maxTrack ++;
  341.     /********************/
  342.     /***** TEMPORAIRE ******/
  343.     /********************/
  344.     
  345.     theMAD->header->Tracks = maxTrack;
  346.     
  347.     starting = 0;
  348.  
  349.     for( i = 0; i < MAXPATTERN; i++) theMAD->partition[ i] = 0L;
  350.  
  351.     for( i = 0; i < theMAD->header->PatMax ; i++)
  352.     {
  353.         theMAD->partition[ i] = (struct    MusicPattern*) NewPtrClear( sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command));
  354.         theMAD->partition[ i]->header.PatternSize = 64L;
  355.         theMAD->partition[ i]->header.CompressionMode = 'NONE';
  356.         
  357.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.PatternName[ x] = 0;
  358.     
  359.         theMAD->partition[ i]->header.PatBytes = 0L;
  360.         theMAD->partition[ i]->header.unused2 = 0L;
  361.     
  362.         MaxPtr = (Ptr) theMAD->partition[ i];
  363.         MaxPtr += sizeof( struct MusicPattern) + theMAD->header->Tracks * 64L * sizeof( struct Command);
  364.  
  365.         Row = 0;
  366.         
  367.         theS3MCopy = (Byte*) theS3M;
  368.         theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  369.         theS3MCopy++;
  370.         
  371.         while( Row < 64)
  372.         {
  373.             /*
  374.                 BYTE:flag,     0        =    end of row
  375.                             &31        =    channel
  376.                             &32        =    follows;  BYTE:note, BYTE:instrument
  377.                             &64        =    follows;  BYTE:volume
  378.                             &128    =    follows; BYTE:command, BYTE:info
  379.             */
  380.             
  381.                 tempChar = *theS3MCopy;
  382.                 theS3MCopy++;
  383.  
  384.                 if( tempChar == 0) Row++;
  385.                 else
  386.                 {
  387.                     // Channel
  388.                     
  389.                     channel = tempChar;
  390.                     channel &= 31;
  391.                     if( channel >= 0 && channel < theMAD->header->Tracks) z = channel;
  392.                     else
  393.                     {
  394.                         DebugStr("\pOut - Channel");
  395.                     }
  396.                     
  397.                     aCmd = GetCommand( Row, z, theMAD->partition[ i]);
  398.  
  399.                     // PERIOD
  400.                     
  401.                     if( (tempChar & 32) != 0)
  402.                     {
  403.                         aCmd->AmigaPeriod = theS3MCopy[ 0];
  404.                         
  405.                         if(    ((aCmd->AmigaPeriod & 0xF0) > 0xD0) ||
  406.                             ((aCmd->AmigaPeriod & 0x0F) > 0x0B)) aCmd->AmigaPeriod = 0;
  407.                         else
  408.                         {
  409.                             Octave = (aCmd->AmigaPeriod & 0xF0) >> 4;
  410.                             Octave -= 2;
  411.                             Note = (aCmd->AmigaPeriod & 0x0F);
  412.                             
  413.                     /*        
  414.                             note_st3period = (8363L * 16L* (long) ( (long) S3Mperiod[ Note] >> (long) Octave )) / 1712L;
  415.                             note_amigaperiod = note_st3period / 4L;
  416.                             
  417.                             aCmd->AmigaPeriod = FoundNoteS3M( note_amigaperiod);
  418.                     */
  419.                             aCmd->AmigaPeriod = Octave*12 + Note;
  420.                             if( aCmd->AmigaPeriod < 0 || aCmd->AmigaPeriod > 80)
  421.                             {
  422.                                 aCmd->AmigaPeriod = 0;
  423.                             }
  424.                         }
  425.                         
  426.                         if( theMAD->instrument[ theS3MCopy[ 1] - 1] != 0) aCmd->InstrumentNo = theS3MCopy[ 1];
  427.                         
  428.                         theS3MCopy += 2L;
  429.                     }
  430.                     
  431.                     // VOLUME
  432.                     
  433.                     if( (tempChar & 64) != 0)
  434.                     {
  435.                         aCmd->EffectCmd = 0x0C;
  436.                         aCmd->EffectArg = theS3MCopy[ 0];
  437.                         
  438.                         if( aCmd->EffectArg > 64) Debugger();
  439.                         
  440.                         theS3MCopy += 1L;
  441.                     }
  442.                     
  443.                     // PARAMETER
  444.                     
  445.                     if( (tempChar & 128) != 0)
  446.                     {
  447.                         if( theS3MCopy[ 0] != 255)
  448.                         {
  449.                             ConvertS3MEffect( theS3MCopy[ 0], theS3MCopy[ 1], &aCmd->EffectCmd, &aCmd->EffectArg);
  450.                         }
  451.                         theS3MCopy += 2L;
  452.                     }
  453.                 }
  454.         }
  455.     }
  456.     aCmd = GetCommand( 0, 0, theMAD->partition[ theMAD->header->oPointers[ 0]]);
  457.     aCmd->EffectCmd = speedE;
  458.     aCmd->EffectArg = s3minfo.initialspeed;
  459.     
  460.     aCmd = GetCommand( 1, 0, theMAD->partition[ theMAD->header->oPointers[ 0]]);
  461.     aCmd->EffectCmd = speedE;
  462.     aCmd->EffectArg = s3minfo.initialtempo;
  463.  
  464.     DisposPtr( (Ptr) s3minfo.orders);        DisposPtr( (Ptr) s3minfo.parapins);
  465.     DisposPtr( (Ptr) s3minfo.parappat);        DisposPtr( (Ptr) s3minfo.insdata);
  466.  
  467.     return noErr;
  468. }
  469.  
  470. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  471. {
  472.     register short len, i;
  473.     
  474.     len = *s2;
  475.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  476. }
  477.  
  478. OSErr ExtractS3MInfo( PPInfoRec *info, Ptr AlienFile)
  479. {
  480.     s3mform    *myS3M = ( s3mform*) AlienFile;
  481.     long        PatternSize;
  482.     short    i;
  483.     short    maxInstru;
  484.     short    tracksNo;
  485.     
  486.     /*** Signature ***/
  487.     
  488.     info->signature = 'S3M ';
  489.     
  490.     /*** Internal name ***/
  491.     
  492.     myS3M->name[ 27] = '\0';
  493.     pStrcpy( info->internalFileName, CtoPstr( myS3M->name));
  494.  
  495.     /*** Total Patterns ***/
  496.     
  497.     info->totalPatterns = 0;
  498.     
  499.     /*** Partition Length ***/
  500.     
  501.     info->partitionLength = 0;
  502.     
  503.     /*** Total Instruments ***/
  504.     
  505.     info->totalInstruments = 0;
  506.     
  507.     pStrcpy( info->formatDescription, "\pS3M Plug");
  508.  
  509.     return noErr;
  510. }
  511.  
  512. OSErr TestS3MFile( Ptr AlienFile)
  513. {
  514. s3mform    *myS3M = ( s3mform*) AlienFile;
  515.  
  516. if(    myS3M->s3msig[ 0] == 'S' &&
  517.     myS3M->s3msig[ 1] == 'C' &&
  518.     myS3M->s3msig[ 2] == 'R' &&
  519.     myS3M->s3msig[ 3] == 'M') return   noErr;
  520.     else return  fileNotSupportedByThisPlug;
  521. }
  522.  
  523. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info, short *MADpitchTable)
  524. {
  525.     OSErr    myErr;
  526.     Ptr        AlienFile;
  527.     short    vRefNum, iFileRefI;
  528.     long    dirID, sndSize;
  529.     
  530. #ifndef powerc
  531.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  532. #endif
  533.  
  534.     HGetVol( 0L, &vRefNum, &dirID);
  535.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  536.  
  537.     myErr = noErr;
  538.  
  539.     switch( order)
  540.     {
  541.         case 'IMPL':
  542.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  543.             if( myErr == noErr)
  544.             {
  545.                 GetEOF( iFileRefI, &sndSize);
  546.             
  547.                 // ** MEMORY Test Start
  548.                 AlienFile = NewPtr( sndSize * 2L);
  549.                 if( AlienFile == 0L) myErr = needMoreMemory;
  550.                 // ** MEMORY Test End
  551.                 
  552.                 else
  553.                 {
  554.                     DisposPtr( AlienFile);
  555.                     
  556.                     AlienFile = NewPtr( sndSize);
  557.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  558.                     if( myErr == noErr)
  559.                     {
  560.                         myErr = TestS3MFile( AlienFile);
  561.                         if( myErr == noErr)
  562.                         {
  563.                             myErr = ConvertS3M2Mad( AlienFile,  GetPtrSize( AlienFile), MadFile);
  564.                         }
  565.                     }
  566.                     DisposPtr( AlienFile);    AlienFile = 0L;
  567.                 }
  568.                 FSClose( iFileRefI);
  569.             }
  570.         break;
  571.         
  572.         case 'TEST':
  573.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  574.             if( myErr == noErr)
  575.             {
  576.                 sndSize = 1024L;
  577.                 
  578.                 AlienFile = NewPtr( sndSize);
  579.                 if( AlienFile == 0L) myErr = needMoreMemory;
  580.                 else
  581.                 {
  582.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  583.                     myErr = TestS3MFile( AlienFile);
  584.                     
  585.                     DisposPtr( AlienFile);    AlienFile = 0L;
  586.                 }
  587.                 FSClose( iFileRefI);
  588.             }
  589.         break;
  590.  
  591.         case 'INFO':
  592.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  593.             if( myErr == noErr)
  594.             {
  595.                 GetEOF( iFileRefI, &info->fileSize);
  596.             
  597.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  598.                 
  599.                 AlienFile = NewPtr( sndSize);
  600.                 if( AlienFile == 0L) myErr = needMoreMemory;
  601.                 else
  602.                 {
  603.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  604.                     if( myErr == noErr)
  605.                     {
  606.                         myErr = ExtractS3MInfo( info, AlienFile);
  607.                     }
  608.                     DisposPtr( AlienFile);    AlienFile = 0L;
  609.                 }
  610.                 FSClose( iFileRefI);
  611.             }
  612.         break;
  613.         
  614.         default:
  615.             myErr = orderNotImplemented;
  616.         break;
  617.     }
  618.  
  619.     HSetVol( 0L, vRefNum, dirID);
  620.  
  621.     #ifndef powerc
  622.         SetA4( oldA4);
  623.     #endif
  624.     return myErr;
  625. }